package com.dlc.longweisheng.chongdianxian.activity;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.widget.ScrollView;
import android.widget.TextView;

import com.aplus.kira.kiralibrary.tools.ByteHexUtil;
import com.dlc.longweisheng.chongdianxian.App;
import com.dlc.longweisheng.chongdianxian.BuildConfig;
import com.dlc.longweisheng.chongdianxian.R;
import com.dlc.longweisheng.chongdianxian.dialog.PasswordDialog;
import com.dlc.longweisheng.chongdianxian.pub.BaseResponse;
import com.dlc.longweisheng.chongdianxian.pub.PasswordResult;
import com.dlc.longweisheng.chongdianxian.pub.PasswordsResponse;
import com.dlc.longweisheng.chongdianxian.pub.TemperatureUsbControl;
import com.dlc.longweisheng.chongdianxian.pub.base.BaseActivity;
import com.dlc.longweisheng.chongdianxian.pub.net.MNet;
import com.google.gson.Gson;
import com.hoho.android.usbserial.util.ByteUtil;
import com.hoho.android.usbserial.util.LogPlus;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.dlc.commonlibrary.okgo.callback.Bean01Callback;
import cn.dlc.commonlibrary.okgo.callback.RawBeanCallback;

public class MainActivity extends BaseActivity {
    @BindView(R.id.tv_id)
    TextView tvId;
    @BindView(R.id.tv_password_des)
    TextView tvPasswordDes;
    @BindView(R.id.tv_passwords)
    TextView tvPasswords;
    @BindView(R.id.sv)
    ScrollView sv;
    private TemperatureUsbControl mTemperatureUsbControl;
    private PasswordDialog passwordDialog;

    @Override
    public int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // TODO: add setContentView(...) invocation
        ButterKnife.bind(this);
        initUsbControl();
    }

    private void getPassword(String macno) {
        MNet.get().getPassword(macno, new Bean01Callback<PasswordResult>() {
            @Override
            public void onSuccess(PasswordResult passwordResult) {
                onGetPassword(1, passwordResult);
            }

            @Override
            public void onFailure(String s, Throwable throwable) {
                showOne(s);
            }
        });

    }

    private void getPassword2(final String deviceId) {
        final String pwd = "cRpwd123";
        MNet.get().getPassword2(deviceId, pwd, new RawBeanCallback<PasswordsResponse>() {
            @Override
            public void onSuccess(PasswordsResponse passwordsResponse) {
                LogPlus.d("passwordsResponse: " + new Gson().toJson(passwordsResponse));
                if (!passwordsResponse.isResultSuccess()) {
                    showOne(passwordsResponse.getMessage());
                    return;
                }
                executePasswords(deviceId, 1, passwordsResponse);
            }

            @Override
            public void onFailure(String s, Throwable throwable) {
                LogPlus.e("onFailure", throwable);
                showOne(s);
            }
        });

    }

    private void getOldPassword(String macno) {
        MNet.get().getOldPassword(macno, new Bean01Callback<PasswordResult>() {
            @Override
            public void onSuccess(PasswordResult passwordResult) {
                if (null != passwordDialog) passwordDialog.dismiss();
                onGetPassword(2, passwordResult);
            }

            @Override
            public void onFailure(String s, Throwable throwable) {
                showOne(s);
            }
        });

    }

    /**
     * @param businessType   1设置密码，2查看密码
     * @param passwordResult
     */
    private void onGetPassword(int businessType, PasswordResult passwordResult) {
        if (businessType == 1) {
            tvPasswordDes.setText("烧录的密码");
        } else {
            tvPasswordDes.setText("查询的密码");
        }

        List<String> passwords = new ArrayList<>();
        List<byte[]> datas = new ArrayList<>();
        datas.add(new byte[]{(byte) 0xFa});
        addData(datas, passwordResult.getData().get_$1());
        addData(datas, passwordResult.getData().get_$2());
        addData(datas, passwordResult.getData().get_$3());
        addData(datas, passwordResult.getData().get_$4());
        addData(datas, passwordResult.getData().get_$5());
        addData(datas, passwordResult.getData().get_$6());
        addData(datas, passwordResult.getData().get_$7());
        addData(datas, passwordResult.getData().get_$8());
        addData(datas, passwordResult.getData().get_$9());

        passwords.addAll(passwordResult.getData().get_$1());
        passwords.addAll(passwordResult.getData().get_$2());
        passwords.addAll(passwordResult.getData().get_$3());
        passwords.addAll(passwordResult.getData().get_$4());
        passwords.addAll(passwordResult.getData().get_$5());
        passwords.addAll(passwordResult.getData().get_$6());
        passwords.addAll(passwordResult.getData().get_$7());
        passwords.addAll(passwordResult.getData().get_$8());
        passwords.addAll(passwordResult.getData().get_$9());

//        byte[] dataBytes = new byte[datas.size()];
//        int k = 0;
//        for (byte[] bytes:datas){
//            dataBytes[k] = bytes[0];
//            k++;
//        }
//        LogPlus.d("spm", "dataBytes:" +new ByteHexUtil().byteArr2HexStr(dataBytes));

        List<String> disList = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < 9; j++) {
                disList.add(passwords.get(i + j * 20));
            }
        }

        StringBuilder builder = new StringBuilder();
        int count = 0;
        for (int i = 0, size = disList.size(); i < size; i++) {
            if (count < 8) {
                count++;
                builder.append(disList.get(i) + " ");
            } else {
                count = 0;
                builder.append(disList.get(i) + "\n");
            }

        }
        tvPasswordDes.setVisibility(View.VISIBLE);
        sv.setVisibility(View.VISIBLE);
        tvPasswords.setText(builder.toString());

        if (businessType == 1) {
            sendDatas(datas, null);
        }
    }

    /**
     * @param deviceId          设备ID
     * @param businessType      1设置密码，2查看密码
     * @param passwordsResponse
     */
    private void executePasswords(final String deviceId, int businessType, final PasswordsResponse passwordsResponse) {
        if (businessType == 1) {
            tvPasswordDes.setText("烧录的密码");
        } else {
            tvPasswordDes.setText("查询的密码");
        }

        List<byte[]> datas = new ArrayList<>();
        String[] _passwords = passwordsResponse.getResponseBean().toPasswordsArray();
        StringBuilder builder = new StringBuilder();
        for (String pwd : _passwords) {
            LogPlus.d("###DATA###", pwd);
            datas.add(ByteUtil.int2Bytes(Integer.parseInt(pwd), 2));
            builder.append(pwd).append(" ");
        }
        datas.add(new byte[]{(byte) 0x14, (byte) 0x15});

        tvPasswordDes.setVisibility(View.VISIBLE);
        sv.setVisibility(View.VISIBLE);
        tvPasswords.setText(builder.toString());

        if (businessType == 1) {
            sendDatas(datas, new IWriteCallback() {
                @Override
                public void onSuccess() {
                    doReportWriteSuccessed(deviceId, passwordsResponse, 3);
                }

                @Override
                public void onFailed(Throwable e) {
                    LogPlus.d("###", e != null ? e.getMessage() : "failed");
                }
            });
        }
    }

    private void doReportWriteSuccessed(String deviceId, PasswordsResponse passwordsResponse, int reportRetryTimes) {
        if (reportRetryTimes <= 0) {
            return;
        }
        String factorsIdx = passwordsResponse.getResponseBean().getFactorsIdx();
        String chargerPwds = passwordsResponse.getResponseBean().getPasswords();
        MNet.get().requestPasswordApplied(deviceId, factorsIdx, chargerPwds, new RawBeanCallback<BaseResponse>() {
            @Override
            public void onSuccess(BaseResponse baseResponse) {
                LogPlus.d("###", "response result:" + baseResponse.getResult());
            }

            @Override
            public void onFailure(String s, Throwable throwable) {
                throwable.printStackTrace();
                LogPlus.d("###", "report failed");
                App.getInstance().getMainHandler().postDelayed(() -> doReportWriteSuccessed(deviceId, passwordsResponse, reportRetryTimes - 1), 1000);
            }
        });
    }

    private void addData(List<byte[]> datas, List<String> passwords) {
        for (int i = 0, size = passwords.size(); i < size; i++) {
            byte[] passwordByte = toByteArray(Integer.parseInt(passwords.get(i)), 2);
            datas.add(new byte[]{passwordByte[1]});
            datas.add(new byte[]{passwordByte[0]});
        }
    }

    /**
     * 初始化USB
     */
    private void initUsbControl() {
        mTemperatureUsbControl = new TemperatureUsbControl(getApplicationContext());
        mTemperatureUsbControl.initUsbControl();
    }

    int times = 0;

    private void sendDatas(final List<byte[]> datas, final IWriteCallback writeCallback) {
        showProgressDialog("正在烧录，请稍候...", 5000, () -> {
            showOne("密码烧录超时，请重试！");
            if (BuildConfig.DEBUG) {
                writeCallback.onSuccess();
            }
        });
        times = 0;
        mTemperatureUsbControl.setSendCallback(result -> {
            LogPlus.d("spm", "result:" + new ByteHexUtil().byteArr2HexStr(result));
            LogPlus.d("spm", "result.length:" + result.length);
            times++;
            LogPlus.d("spm", "times:" + times);
            if (times < 3) {
                sendDatasOnThread(datas);
                return;
            }

            dismissProgressDialog();
            boolean isSuccess = result.length >= /*361*/42;
            showOne(isSuccess ? "密码烧录成功！" : "密码烧录失败，请重试！");
            if (writeCallback != null) {
                if (isSuccess) writeCallback.onSuccess();
                else writeCallback.onFailed(new Exception("密码烧录失败"));
            }
        });
        sendDatasOnThread(datas);
    }

    private void sendDatasOnThread(final List<byte[]> datas) {
        LogPlus.d("spm", "sendDatasOnThread");
        new Thread() {
            @Override
            public void run() {
                super.run();
                if (!使用新的密码规则及接口) {
                    for (byte[] data : datas) {
                        try {
                            mTemperatureUsbControl.writeAsync(data);
                        } catch (Throwable e) {
                            e.printStackTrace();
                            LogPlus.e("异常,", e);
                        }
                        SystemClock.sleep(5);
                    }
                }
                if (使用新的密码规则及接口) {
                    int datasLength = 0;
                    for (byte[] data : datas) {
                        datasLength += data.length;
                    }
                    byte[] frameData = new byte[datasLength];
                    int writeIndex = 0;
                    for (byte[] data : datas) {
                        System.arraycopy(data, 0, frameData, writeIndex, data.length);
                        writeIndex += data.length;
                    }
                    try {
                        mTemperatureUsbControl.writeAsync(frameData);
                    } catch (Throwable e) {
                        e.printStackTrace();
                        LogPlus.e("异常,", e);
                    }
                    SystemClock.sleep(5);
                }
            }
        }.start();
    }


    private byte[] toByteArray(int iSource, int iArrayLen) {
        byte[] bLocalArr = new byte[iArrayLen];
        for (int i = 0; (i < 4) && (i < iArrayLen); i++) {
            bLocalArr[i] = (byte) (iSource >> 8 * i & 0xFF);
        }
        return bLocalArr;
    }

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter usbFilter = new IntentFilter();
        usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(mUsbReceiver, usbFilter);
        mTemperatureUsbControl.initUsbControl();
        mTemperatureUsbControl.startIoManager();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mTemperatureUsbControl.stopIoManager();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mTemperatureUsbControl.onPause();
        unregisterReceiver(mUsbReceiver);
    }


    private java.util.Map<UsbDevice, Long> requestPermissionDevices = new ConcurrentHashMap<>();
    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {//usb设备插入
                //设备插入
                LogPlus.e("spm", "ACTION_USB_DEVICE_ATTACHED");

                requestPermissionDevices.clear();

                UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
                UsbDevice device_add = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (device_add != null) {
                    if (usbManager.hasPermission(device_add)) {
                        mTemperatureUsbControl.initUsbControl();
                        mTemperatureUsbControl.onDeviceStateChange();
                        return;
                    }
                    if (requestPermissionDevices.containsKey(device_add)) {
                        return;
                    }
                    requestPermissionDevices.put(device_add, System.currentTimeMillis());

                    PendingIntent pendingIntent = getPendingIntent(0, new Intent(ACTION_USB_PERMISSION));
                    usbManager.requestPermission(device_add, pendingIntent);
                }
            } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                //设备移除
                mTemperatureUsbControl.onPause();
                LogPlus.e("spm", "ACTION_USB_DEVICE_DETACHED");
            } else if (ACTION_USB_PERMISSION.equals(action)) {//自定义广播 授权usb
                requestPermissionDevices.clear();
                UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { //允许权限申请
                    LogPlus.d("用户已授权 usbDevice:" + usbDevice);
                } else {
                    LogPlus.d("用户未授权");
                }
            }
        }
    };


    @SuppressLint("SetTextI18n")
    @OnClick({R.id.btn_scan, R.id.btn_check, R.id.btn_revise_password, R.id.btn_set_host})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.btn_scan:
                toScan();
                break;
            case R.id.btn_check:
                showPasswordDialog();
                break;
            case R.id.btn_revise_password:
                startActivity(RevisePasswordActivity.class);
                break;
            case R.id.btn_set_host:
                startActivity(ReviseHostActivity.class);
                break;
        }
    }

    private static final boolean 使用新的密码规则及接口 = true;

    @SuppressLint("SetTextI18n")
    private void toScan() {
        if (BuildConfig.DEBUG) {
            startActivity(ScanActivity.class, 1, intent -> {
                try {
                    String deviceId = parseDeviceId(intent);
                    tvId.setText("正在烧录ID:" + deviceId);
                    if (!使用新的密码规则及接口) getPassword(deviceId);
                    if (使用新的密码规则及接口) getPassword2(deviceId);
                } catch (Exception e) {
                    e.printStackTrace();
                    showOne("二维码不合法");
                }
            });
            return;
        }
        if (!mTemperatureUsbControl.isConnect()) {
            showOne("请先连接充电线");
            return;
        }
        startActivity(ScanActivity.class, 1, intent -> {
            try {
                String deviceId = parseDeviceId(intent);
                tvId.setText("正在烧录ID:" + deviceId);
                if (!使用新的密码规则及接口) getPassword(deviceId);
                if (使用新的密码规则及接口) getPassword2(deviceId);
            } catch (Exception e) {
                e.printStackTrace();
                showOne("二维码不合法");
            }
        });
        //getPassword("19082700028");
    }

    private void showPasswordDialog() {
        if (passwordDialog == null) {
            passwordDialog = new PasswordDialog(this);
            passwordDialog.setPostClickListener(view -> {
                if (!passwordDialog.isPasswordRight()) {
                    showOne("密码错误");
                    return;
                }
                //查询密码
                startActivity(ScanActivity.class, 2, intent -> {
                    try {
                        String deviceId = parseDeviceId(intent);
                        tvId.setText("查询的ID:" + deviceId);
                        getOldPassword(deviceId);
                    } catch (Throwable e) {
                        e.printStackTrace();
                        showOne("二维码不合法");
                    }
                });
            });
        }
        if (passwordDialog != null) passwordDialog.show();
    }

    private String parseDeviceId(Intent intent) throws IllegalArgumentException {
        String content = intent.getStringExtra("content");
        if (!使用新的密码规则及接口) {
            String[] contents = content.split("macno=");
            if (contents.length > 1) {
                contents = contents[1].split("&");
                return contents[0];
            }
        }
        if (使用新的密码规则及接口) {
            final String beginKeyword = "ID=";
            int beginIndex = content.lastIndexOf(beginKeyword);
            if (-1 != beginIndex) {
                String idStr = content.substring(beginIndex + beginKeyword.length());
                Matcher idMatcher = Pattern.compile("(\\d+)").matcher(idStr);
                if (idMatcher.find()) {
                    return idMatcher.group(1);
                }
            }
        }
        throw new IllegalArgumentException("二维码不合法");
    }

    private interface IWriteCallback {
        void onSuccess();

        void onFailed(Throwable e);
    }

    private PendingIntent getPendingIntent(int requestCode, Intent intent) {
        return PendingIntent.getBroadcast(this, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    public static final String ACTION_USB_PERMISSION = "com.android.charger.USB_PERMISSION";
}
